import * as d3 from 'd3'
export class MultiSignScatterChart {
  divId = ''
  data = []
  chart = {}
  category = []
  color = d3.scaleOrdinal(d3.schemeCategory10)
  shape = [0, 1, 2, 3, 4, 5, 6]
  colorScale = {}
  constructor (divId) {
    this.divId = divId
  }

  draw () {
    this.initChart()
    this.initAxis()
    this.drawLabel()
    this.drawLegend()
    this.drawDot()
  }

  update () {
    this.initAxis()
    this.drawLegend()
    this.drawDot()
  }

  initChart () {
    this.chart.padding = {
      left: 20,
      right: 50,
      top: 20,
      bottom: 20
    }
    this.chart.divHeight = document.getElementById(this.divId).offsetHeight -
      this.chart.padding.top -
      this.chart.padding.bottom
    this.chart.divWidth = document.getElementById(this.divId).offsetWidth -
      this.chart.padding.left -
      this.chart.padding.right

    this.chart.svg = d3
      .select('#' + this.divId)
      .append('svg')
      .attr('width', this.chart.divWidth +
        this.chart.padding.left +
        this.chart.padding.right
      )
      .attr('height', this.chart.divHeight +
        this.chart.padding.top +
        this.chart.padding.bottom
      )
      .attr('class', 'svg_chart')
  }

  getCategory () {
    let cateNum = 0
    for (let i = 0; i < this.category.length; ++i) {
      this.colorScale[this.category[i]] = this.color(cateNum)
      cateNum += 1
    }
  }

  initAxis () {
    this.chart.xScale = d3.scaleLinear()
      .domain([0, d3.max(this.data, function (d) {
        return +d.x
      })])
      .range([this.chart.padding.left, this.chart.divWidth])

    this.chart.yScale = d3.scaleLinear()
      .domain([0, d3.max(this.data, function (d) {
        return +d.y
      })])
      .range([this.chart.divHeight, this.chart.padding.top])

    this.chart.rScale = d3.scaleLinear()
      .domain(this.data.map(d => d.value))
      .range([4, 10])

    this.chart.shapeScale = d3.scaleOrdinal()
      .domain(this.category)
      .range(this.shape)

    this.chart.xAxis = d3
      .axisBottom()
      .scale(this.chart.xScale)
      .ticks(this.data.length)
    //   .tickFormat((d) => 2015 + parseInt(d))
    this.chart.yAxis = d3.axisLeft().scale(this.chart.yScale)

    if (this.chart.svg.select('.xAxis')._groups[0][0] !== undefined) {
      this.chart.svg.select('.xAxis').call(this.chart.xAxis)
    } else {
      this.chart.svg
        .append('g')
        .attr('class', 'xAxis')
        .attr('transform', 'translate(0,' + this.chart.divHeight + ')')
        .call(this.chart.xAxis)
    }

    if (this.chart.svg.select('.yAxis')._groups[0][0] !== undefined) {
      this.chart.svg.select('.yAxis').call(this.chart.yAxis)
    } else {
      this.chart.svg
        .append('g')
        .attr('class', 'yAxis')
        .attr('transform', 'translate(' + this.chart.padding.left + ')')
        .call(this.chart.yAxis)
    }
  }

  drawDot () {
    let dots = this.chart.svg.selectAll('.dot')
      .data(this.data, d => d.id)

    dots.select('path')
      .transition()
      .duration(750)
      .attr('transform', d => {
        return 'translate(' + this.chart.xScale(d.x) + ',' + this.chart.yScale(d.y) + ')'
      })

    let dotsEnter = dots.enter()
      .append('g')
      .attr('class', 'dot')

    dotsEnter.append('path')
      .attr('transform', d => {
        return 'translate(' + this.chart.xScale(d.x) + ',' + this.chart.yScale(d.y) + ')'
      })
      .attr('d', d3.symbol().type(d => d3.symbols[this.chart.shapeScale(d.category)]).size(0))
      .attr('class', 'symbol')
      .style('fill', d => this.colorScale[d.category])
      .style('stroke', 'black')
      .transition()
      .duration(750)
      .attr('d', d3.symbol().type(d => d3.symbols[this.chart.shapeScale(d.category)]).size(50))

    let dotsExit = dots.exit()
      .transition()
      .duration(750)
      .remove()

    dotsExit.select('path')
      .attr('d', d3.symbol().type(d => d3.symbols[this.chart.shapeScale(d.category)]).size(0))
  }

  drawLabel () {
    // 标题
    this.chart.svg
      .append('text')
      .attr('x', this.chart.divWidth / 2 - this.title.length)
      .attr('y', this.chart.divHeight + this.chart.padding.bottom * 1.7)
      .text(this.title)
    // y轴
    this.chart.svg
      .append('text')
      .attr('x', this.chart.padding.left)
      .attr('y', this.chart.padding.top - 5)
      .text(this.yLabel)
    // x轴
    this.chart.svg
      .append('text')
      .attr('x', this.chart.divWidth + 5)
      .attr('y', this.chart.divHeight)
      .text(this.xLabel)
  }

  drawLegend () {
    this.getCategory()
    let legendWidth = 15
    let legendHeight = 15
    let legends = this.chart.svg
      .selectAll('.legend')
      .data(this.category)
    let legendEnter = legends.enter()
      .append('g')
      .attr('class', 'legend')

    legendEnter.append('path')
      .attr('d', d3.symbol().type((d, i) => {
        return d3.symbols[this.chart.shapeScale(d)]
      }).size(0))
      .attr('transform', (_, i) => {
        return 'translate(' + (this.chart.divWidth + 15) + ',' + (this.chart.padding.top + legendHeight * i) + ')'
      })
      .style('fill', (_, i) => this.color(i))

    legendEnter.append('text')
      .attr('x', this.chart.divWidth + legendWidth * 1.3 + 10)
      .attr('y', (_, i) => this.chart.padding.top + legendHeight * i + legendHeight * 0.3)
      .text(String)
      .style('font-size', 1e-6)

    let legendUpdate = legendEnter.merge(legends)

    legendUpdate.select('path')
      .transition()
      .duration(750)
      .attr('d', d3.symbol().type((_, i) => d3.symbols[i]).size(50))

    legendUpdate.select('text')
      .transition()
      .duration(750)
      .style('font-size', 10)

    let legendExit = legends.exit()
      .transition()
      .duration(750)
      .remove()

    legendExit.select('path')
      .attr('d', d3.symbol().type((_, i) => {
        return d3.symbols[i]
      }).size(0))

    legendExit.select('text')
      .style('stroke-opacity', 1e-6)
  }
}
